package com.spzx.cart.service.impl;

import com.spzx.cart.api.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.HttpStatus;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.vo.SkuPrice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements ICartService {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RemoteProductService remoteProductService;

    private String getCartKey(Long userId) {
        return "user:cart:" + userId;
    }

    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        //获取当前登录用户ID
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        //构建用户购物车数据存储结构
        BoundHashOperations hashOperations = redisTemplate.boundHashOps(cartKey);
        String hashKey = skuId.toString();
        if (!hashOperations.hasKey(hashKey)) {
            //购物车种类添加上限判断
            if (hashOperations.size() >= 50) {
                //若本次添加后,购物车商品种类数量超过上限(上限50),则添加失败
                throw new ServiceException("购物车已满");
            }
            //首次添加购物车
            CartInfo cartInfo = new CartInfo();
            cartInfo.setUserId(userId);
            cartInfo.setSkuId(skuId);
            cartInfo.setSkuNum(1);

            //其余信息调用远程接口,根据skuId调用商品服务接口,查询ProductSku商品信息
            //调用Feign接口,传入所需参数,和inner请求头(表示内部调用)
            R<ProductSku> productSkuFromDB = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            //调用Feign接口,需要进行结果降级判断
            if (productSkuFromDB.getCode() == HttpStatus.ERROR) {
                throw new ServiceException(productSkuFromDB.getMsg());
            }
            //接收接口返回结果数据
            ProductSku productSku = productSkuFromDB.getData();
            //封装结果至返回对象
            cartInfo.setCartPrice(productSku.getSalePrice());
            cartInfo.setSkuPrice(productSku.getSalePrice());
            cartInfo.setThumbImg(productSku.getThumbImg());
            cartInfo.setSkuName(productSku.getSkuName());
            cartInfo.setCreateTime(new Date());
            hashOperations.put(hashKey, cartInfo);
        } else {
            //非首次添加购物车
            CartInfo cartInfo = (CartInfo) hashOperations.get(hashKey);
            int nums = cartInfo.getSkuNum() + skuNum;
            //判断单个商品数量上限(上限99)
            cartInfo.setSkuNum(nums > 99 ? 99 : nums);
            cartInfo.setCreateTime(new Date());
            hashOperations.put(hashKey, cartInfo);
        }
    }

    @Override
    public List<CartInfo> cartList() {
        //获取当前登录用户userId , 获取缓存中用户相关商品数据Key
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);

        BoundHashOperations hashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOperations.values();

        //数据判空
        if (CollectionUtils.isEmpty(cartInfoList)) {
            return new ArrayList<CartInfo>();
        }

        //远程调用商品列表,获取最新价格
        List<Long> skuIdList = cartInfoList.stream().map(CartInfo::getSkuId).toList();
        R<List<SkuPrice>> skuPriceListFromDB = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);

        //调用远程接口需进行降级判断
        if (skuPriceListFromDB.getCode() == HttpStatus.ERROR) {
            throw new ServiceException(skuPriceListFromDB.getMsg());
        }
        List<SkuPrice> skuPriceList = skuPriceListFromDB.getData();
        log.info("数据库价格信息",skuPriceList);

        Map<Long, BigDecimal> skuIdToSkuPriceMap = skuPriceList.stream().collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));

        for (CartInfo cartInfo : cartInfoList) {
            BigDecimal skuPrice = skuIdToSkuPriceMap.get(cartInfo.getSkuId());
            cartInfo.setSkuPrice(skuPrice);
        }

        //数据并排序
        cartInfoList.stream().sorted((o1, o2) ->
                o2.getCreateTime().compareTo(o1.getCreateTime())
        ).collect(Collectors.toList());

        return cartInfoList;
    }

    @Override
    public void deleteCart(Long skuId) {
        //获取线程用户数据
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);

        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        //于Redis缓存中删除skuId数据
        hashOperations.delete(skuId.toString());
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        //获取线程用户数据
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);

        //从缓存中获取用户选中商品skuId
        if (hashOperations.hasKey(skuId.toString())) {
            CartInfo cartInfo = hashOperations.get(skuId.toString());
            //更新商品状态
            cartInfo.setIsChecked(isChecked);
            //存入缓存
            hashOperations.put(skuId.toString(), cartInfo);
        }
    }

    @Override
    public void allCheckCart(Integer isChecked) {
        //获取线程用户数据
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);

        List<CartInfo> cartInfoList = hashOperations.values();

        if (!CollectionUtils.isEmpty(cartInfoList)) {
            for (CartInfo cartInfo : cartInfoList) {
                cartInfo.setIsChecked(isChecked);
                hashOperations.put(cartInfo.getSkuId().toString(), cartInfo);
            }
        }
    }

    @Override
    public void clearCart() {
        //获取线程用户数据
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        redisTemplate.delete(cartKey);
    }

    @Override
    public Boolean updateCartPrice(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        //获取缓存中购物车信息
        List<CartInfo> cartInfoList = hashOperations.values();
        //调用商品服务接口,获取商品最新价格
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            List<Long> skuIdList = cartInfoList.stream()
                    .filter((cartInfo) -> cartInfo.getIsChecked() == 1)
                    .map(CartInfo::getSkuId).toList();
            R<List<SkuPrice>> skuPriceListFromDB = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
            if (skuPriceListFromDB.getCode() == HttpStatus.ERROR){
                throw new ServiceException(skuPriceListFromDB.getMsg());
            }
            List<SkuPrice> skuPriceList = skuPriceListFromDB.getData();

            //更新选中商品
            Map<Long, BigDecimal> skuIdToSkuPriceMap = skuPriceList.stream().collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
            for (CartInfo cartInfo : cartInfoList) {
                //金额变量转换为BigDecimal类型
                BigDecimal skuSalePrice = skuIdToSkuPriceMap.get(cartInfo.getSkuId());
                cartInfo.setCartPrice(skuSalePrice);
                cartInfo.setSkuPrice(skuSalePrice);
                hashOperations.put(cartInfo.getSkuId().toString(),cartInfo);
            }
        }
        return true;
    }

    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = boundHashOperations.values();

        if (!CollectionUtils.isEmpty(cartInfoList)){
            for (CartInfo cartInfo : cartInfoList) {
                if (cartInfo.getIsChecked().intValue() == 1){
                    boundHashOperations.delete(cartInfo.getSkuId().toString());
                }
            }
        }

        return true;
    }

    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        List<CartInfo> cartInfoCheckedList = new ArrayList<>();
        String cartKey = getCartKey(userId);
        List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(cartKey);
        if (!CollectionUtils.isEmpty(cartInfoList)){
            for (CartInfo cartInfo : cartInfoList) {
                if (cartInfo.getIsChecked().equals(1)){
                    cartInfoCheckedList.add(cartInfo);
                }
            }
        }
        return cartInfoCheckedList;
    }
}